package cn.liutao.common.filter;

import cn.hutool.core.text.AntPathMatcher;
import cn.hutool.core.util.StrUtil;
import cn.liutao.auth.entity.dto.UserDto;
import cn.liutao.auth.entity.po.User;
import cn.liutao.common.entity.LoginUser;
import cn.liutao.common.enums.CommonEnum;
import cn.liutao.common.exception.ForbiddenException;
import cn.liutao.common.exception.OrderException;
import cn.liutao.common.exception.UnauthorizedException;
import cn.liutao.common.utils.JwtUtils;
import cn.liutao.common.utils.RedisUtils;
import cn.liutao.common.utils.ServletUtils;
import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @author liutao
 * @Description TOKEN拦截过滤器
 * @date 2023/10/30 23:15
 * @Version 1.0
 */
@Slf4j
public class TokenFilter extends HttpFilter {



    private List<String> doFilterPathList = Arrays.asList(
            "/order_system/auth/login",
            "/order_system/auth/register",
            "/order_system/auth/captcha",
            "/order_system/dish",
            "/order_system/cuisine",
            "/order_system/images/*",
            "/order_system/order/alipay",
            "/order_system/order/payresult",
            "/auth/login",
            "/auth/register",
            "/auth/captcha",
            "/images/*",
            "/dish",
            "/cuisine",
            "/order/alipay",
            "/order/payresult"
    );

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        JwtUtils jwtUtils = new JwtUtils();
        String requestURI = request.getRequestURI();
        //过滤预请求
        String method = request.getMethod();
        if ("OPTIONS".equals(method)){
            chain.doFilter(request,response);
            return;
        }
        //过滤无需访问的路径
        log.debug("当前请求路径：{}",requestURI);
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        for (String url : doFilterPathList) {
            if (antPathMatcher.match(url,requestURI)){
                log.info("过滤了本次请求：【{}】",requestURI);
                doFilter(request,response,chain);
                return;
            }
        }
        User user = null;
        try {
            //校验token 格式
            String jwt = request.getHeader(jwtUtils.getHeader());

            if (StrUtil.isBlank(jwt)) {
                throw new ForbiddenException("token 不能为空");
            }

            String[] tokens = jwt.split(" ");
            if (tokens.length != 2 && !"Bearer".equals(tokens[0])) {
                throw new ForbiddenException("token 格式异常");
            }

            String authorization = tokens[1];
            //校验token
            Claims claim = jwtUtils.getClaimsByToken(authorization);
            if (claim == null) {
                throw new ForbiddenException("token 异常");
            }

            if (jwtUtils.isTokenExpired(claim)) {
                throw new UnauthorizedException("登陆 已过期");
            }
            //获取用户信息
            String subject = claim.getSubject();
            if ("".equals(subject)||subject==null){
                throw new UnauthorizedException("登陆 已过期");
            }
            UserDto userDto = JSONObject.parseObject(subject, UserDto.class);
            if (userDto==null){
                throw new UnauthorizedException("登陆 已过期");
            }
            user = userDto;
            String key;
            //拼接key
            if (userDto.getIsAdmin().compareTo(CommonEnum.SYS_IS_ADMIN.getIntValue())==0){
                //管理员
                key= CommonEnum.LOGIN_KEY.getValue()+CommonEnum.SYS_IS_ADMIN.getDesc()+ userDto.getUsername();
            }else{
                //非管理员
                key= CommonEnum.LOGIN_KEY.getValue()+CommonEnum.SYS_NOT_ADMIN.getDesc()+ userDto.getUsername();
            }
            //判断单点登录
            String loginToken = RedisUtils.get(key);
            if (!loginToken.equals(authorization)) {
                throw new UnauthorizedException("该账号已在别处登陆");
            }
        }catch (OrderException e){
            //在过滤器进行统一异常处理
            log.info("过滤器中发现异常:{}",e.getMessage(),e);
            ServletUtils.error(response,e.getMessage());
            return;
        }catch (UnauthorizedException e){
            log.info("过滤器中发现异常:{}",e.getMessage(),e);
            ServletUtils.error(response,e.getMessage(),e.getStatus());
            return;
        }catch (ForbiddenException e){
            log.info("过滤器中发现异常:{}",e.getMessage(),e);
            ServletUtils.error(response,e.getMessage(),e.getStatus());
            return;
        }

        LoginUser.addLoginUser(user);
        doFilter(request,response,chain);
        //清除用户信息
        LoginUser.removeLoginUser();
    }


}
